package czy.demo.controller;


import czy.demo.pojo.User;
import czy.demo.util.JsonUtil;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.Map;

@RestController
@RequestMapping("/param")
public class ParameterController {


    /**
     * 路径变量必须使用PathVariable注解注入参数,不使用注入不了
     */
    @GetMapping("/path/{name}/{age}")
    public String path(@PathVariable String name, @PathVariable int age){
        System.out.println("path接收到参数:");
        System.out.println("name:"+name);
        System.out.println("age:"+age);
        return "name="+name+"&age="+age;
    }

    /**
     * get请求时可以直接通过属性名获取查询字符串参数,此时属性名必须与查询字符串参数名对应
     * 如果参数类型不能转换,会报错
     * 比如参数中缺少name,则name为null,此时不会报错
     * 但是如果缺少age,由于age不能为null,此时就会报错
     * 所以,如果缺少参数,则参数设置为null,这个过程才会报错
     */
    @GetMapping("/get/query")
    public String query(String name,int age){
        System.out.println("query接收到参数:");
        System.out.println("name:"+name);
        System.out.println("age:"+age);
        return "name="+name+"&age="+age;
    }

    /**
     * 如果查询字符串参数名与属性名不对应,需要使用RequestParam注解指定参数名
     * 这里RequestParam与RequestPart作用相同
     */
    @GetMapping("/get/query1")
    public String query1(@RequestPart("name") String name1, int age){
        System.out.println("query1接收到参数:");
        System.out.println("name:"+name1);
        System.out.println("age:"+age);
        return "name="+name1+"&age="+age;
    }

    /**
     * 查询参数可以使用对象来接收,框架会自动将字段设置到对象
     * 传递参数时可以使用.符号传递对象属性，如
     * ?name=zhangsan&amp; age=12&amp; address.desc=梨园路&amp; address.city.province=陕西省&amp; address.city.city=西安市&amp; address.city.town=高新区
     * .符号可以作为对象属性的指示符，此时User对象的对象属性也会被赋值
     */
    @GetMapping("/get/query/obj")
    public String queryObj(User user){
        System.out.println("queryObj接收到参数:"+ JsonUtil.toJson(user));
        return user.toString();
    }

    /**
     * 使用post请求时,也可以直接使用同名属性接收请求参数
     * 注意:此时如果查询字符串中有同名参数,会合并
     * 即查询字符串中name参数会与表单请求name参数合并
     * name=lisi,zhangsan
     * 相应的,当请求参数名与属性名不一致时,可以使用RequestParam指定参数名
     */
    @PostMapping("/post/form")
    public String form(String name,int age){
        System.out.println("form接收到参数:");
        System.out.println("name:"+name);
        System.out.println("age:"+age);
        return "name="+name+"&age="+age;
    }

    /**
     * 表单请求也可以直接使用对象接收字段
     */
    @PostMapping("/post/form/obj")
    public String formObj(User user){
        System.out.println("form接收到参数:");
        System.out.println(user);
        return user.toString();
    }

    /**
     * 当接收form-data类型的post请求时,可以使用MultipartFile接收上传文件
     * 其他规则与上面相同
     */
    @PostMapping("/post/data")
    public String data(String name, int age, MultipartFile file){
        System.out.println("data接收到参数:");
        System.out.println("name:"+name);
        System.out.println("age:"+age);
        System.out.println("文件名:"+file.getOriginalFilename());
        System.out.println("文件类型:"+file.getContentType());
        return "name="+name+"&age="+age+"&file="+file.getOriginalFilename();
    }

    /**
     * form-data请求也可以使用对象来接收参数
     * 这里只是把name age字段用对象接收
     * file字段没有
     */
    @PostMapping("/post/data/obj")
    public String dataObj(User user, MultipartFile file){
        System.out.println("data接收到参数:");
        System.out.println(user);
        System.out.println("文件名:"+file.getOriginalFilename());
        System.out.println("文件类型:"+file.getContentType());
        return user.toString()+"&file="+file.getOriginalFilename();
    }

    /** json请求不能直接获取其中字段,可以直接使用RequestBody获取请求体,进行解析
     *  其他类型请求如表单请求也可以获取请求体
     *  但是form-data请求获取不到请求体
     */
    @PostMapping("/post/json")
    public String json(@RequestBody String body){
        System.out.println("json接收到参数:");
        System.out.println(body);
        return body;
    }

    /**
     * json类型请求也可以使用对象接收请求,此时必须使用RequestBody注解
     */
    @PostMapping("/post/json/obj")
    public String jsonObj(@RequestBody User user){
        System.out.println("json接收到参数:");
        System.out.println(user);
        return user.toString();
    }

    /**
     * 直接使用Map获取请求体,只有json请求体可以这样获取
     * 这样获取有一个特点,可以嵌套获取深层次属性,如请求体为:
     * {
     * 	"a":"aa",
     * 	"b":"bb",
     * 	"user":{
     * 		"name":"张三",
     * 		"age":12
     *        }
     * },获取到Map为:
     * 键为:a
     * 值为:aa
     * 值类型为:java.lang.String
     * 键为:b
     * 值为:bb
     * 值类型为:java.lang.String
     * 键为:user
     * 值为:{name=张三, age=12}
     * 值类型为:java.util.LinkedHashMap
     * 可以看到除了字符串整数类型的值,也可以获取对象类型的值
     * 对象被嵌套转换为LinkedHashMap
     */
    @PostMapping("/post/json/map")
    public String map(@RequestBody Map<String,Object> params){
        for(Map.Entry<String,Object> entry:params.entrySet()){
            System.out.println("键为:"+entry.getKey());
            System.out.println("值为:"+entry.getValue());
            System.out.println("值类型为:"+entry.getValue().getClass().getName());
        }
        return "success";
    }

}
